"""
Conversation Manager for Cross-Temporal Multi-Participant Dialogues.

This module manages multi-participant dialogue coordination, turn-taking,
context preservation, and session state management for cross-temporal conversations.
"""

import numpy as np
import logging
import asyncio
import time
import uuid
from typing import Dict, List, Optional, Tuple, Any, Set, Union
from dataclasses import dataclass, field
from enum import Enum
from collections import defaultdict, deque
import json
from datetime import datetime

from ..personality.models import PersonalityVector
from ..memory.manager import MemoryManager
from .cross_temporal_generator import CrossTemporalDialogueGenerator, DialogueContext, GenerationRequest

logger = logging.getLogger(__name__)


class ConversationState(Enum):
    """Conversation state management."""
    INITIALIZING = "initializing"
    ACTIVE = "active"
    PAUSED = "paused"
    COMPLETED = "completed"
    ARCHIVED = "archived"
    ERROR = "error"


class TurnPolicy(Enum):
    """Turn-taking policies for multi-participant conversations."""
    ROUND_ROBIN = "round_robin"
    RANDOM = "random"
    SMART_CONTEXTUAL = "smart_contextual"
    FACILITATOR_CONTROLLED = "facilitator_controlled"


@dataclass
class ConversationParticipant:
    """Enhanced participant model for conversation management."""
    participant_id: str
    name: str
    personality_vector: PersonalityVector
    historical_period: str
    cultural_background: str
    role: str = "participant"
    expertise_areas: List[str] = field(default_factory=list)
    speaking_style: str = "default"
    is_active: bool = True
    turn_priority: float = 1.0  # Higher = more likely to speak next
    engagement_level: float = 1.0  # 0.0-1.0 scale
    last_activity: Optional[datetime] = None
    message_count: int = 0
    average_response_time: float = 0.0


@dataclass
class ConversationMessage:
    """Enhanced message model with conversation context."""
    message_id: str
    conversation_id: str
    participant_id: str
    content: str
    timestamp: datetime
    turn_number: int
    response_to: Optional[str] = None
    accuracy_score: float = 0.0
    cultural_authenticity: float = 0.0
    confidence_score: float = 0.0
    engagement_score: float = 0.0
    historical_appropriateness: float = 0.0
    metadata: Dict[str, Any] = field(default_factory=dict)


@dataclass
class ConversationTopic:
    """Topic tracking for conversation flow."""
    topic_id: str
    name: str
    description: str
    historical_context: str
    participants_involved: List[str]
    start_turn: int
    end_turn: Optional[int] = None
    engagement_level: float = 0.0
    learning_objectives_addressed: List[str] = field(default_factory=list)


@dataclass
class ConversationAnalytics:
    """Comprehensive conversation analytics."""
    total_turns: int = 0
    total_messages: int = 0
    participants_stats: Dict[str, Dict[str, Any]] = field(default_factory=dict)
    topic_progression: List[ConversationTopic] = field(default_factory=list)
    engagement_over_time: List[Tuple[int, float]] = field(default_factory=list)
    accuracy_over_time: List[Tuple[int, float]] = field(default_factory=list)
    cultural_authenticity_over_time: List[Tuple[int, float]] = field(default_factory=list)
    anachronisms_detected: int = 0
    corrections_applied: int = 0
    cross_temporal_interactions: int = 0  # Interactions between different eras
    learning_objectives_progress: Dict[str, float] = field(default_factory=dict)


class ConversationManager:
    """
    Advanced conversation manager for multi-participant cross-temporal dialogues.
    
    Features:
    - Multi-participant dialogue coordination
    - Intelligent turn-taking management
    - Context preservation across conversation turns
    - Session state management and persistence
    - Real-time conversation analytics
    - Cross-temporal interaction facilitation
    """
    
    def __init__(
        self,
        conversation_id: str,
        context: DialogueContext,
        dialogue_generator: CrossTemporalDialogueGenerator,
        memory_manager: MemoryManager,
        participants: List[ConversationParticipant],
        turn_policy: TurnPolicy = TurnPolicy.SMART_CONTEXTUAL,
        max_turns: int = 1000,
        max_context_length: int = 50
    ):
        """
        Initialize conversation manager.
        
        Args:
            conversation_id: Unique conversation identifier
            context: Dialogue context for the conversation
            dialogue_generator: Generator for creating responses
            memory_manager: Memory system for persistence
            participants: List of conversation participants
            turn_policy: Policy for managing turn-taking
            max_turns: Maximum number of turns
            max_context_length: Maximum conversation context length
        """
        self.conversation_id = conversation_id
        self.context = context
        self.dialogue_generator = dialogue_generator
        self.memory_manager = memory_manager
        self.participants = {p.participant_id: p for p in participants}
        self.turn_policy = turn_policy
        self.max_turns = max_turns
        self.max_context_length = max_context_length
        
        # Conversation state
        self.state = ConversationState.INITIALIZING
        self.created_at = datetime.now()
        self.started_at = None
        self.completed_at = None
        self.last_activity = datetime.now()
        
        # Turn management
        self.current_turn = 0
        self.current_speaker = None
        self.next_speaker = None
        self.turn_history = []  # List of (turn_number, participant_id)
        self.speaking_queue = deque()
        
        # Message storage
        self.messages = deque(maxlen=max_turns)
        self.message_index = {}  # message_id -> ConversationMessage
        
        # Context management for coherent conversations
        self.conversation_context = deque(maxlen=max_context_length)
        self.topic_tracking = []
        self.current_topic = None
        
        # Analytics and monitoring
        self.analytics = ConversationAnalytics()
        
        # Performance tracking
        self.performance_stats = {
            'total_generation_time': 0.0,
            'average_turn_time': 0.0,
            'successful_turns': 0,
            'failed_turns': 0,
            'context_switches': 0,
            'cross_temporal_exchanges': 0
        }
        
        logger.info(f"ConversationManager initialized for {conversation_id} with {len(participants)} participants")
    
    async def start_conversation(self, initial_prompt: Optional[str] = None) -> ConversationMessage:
        """
        Start the conversation with optional initial prompt.
        
        Args:
            initial_prompt: Optional prompt to begin the conversation
            
        Returns:
            Initial conversation message
        """
        if self.state != ConversationState.INITIALIZING:
            raise ValueError(f"Cannot start conversation in {self.state.value} state")
        
        self.state = ConversationState.ACTIVE
        self.started_at = datetime.now()
        
        # Initialize turn management
        self._initialize_turn_management()
        
        # Create initial message if prompt provided
        if initial_prompt:
            # Use first participant or facilitator for initial prompt
            initial_speaker = self._select_initial_speaker()
            
            initial_message = await self._add_system_message(
                content=initial_prompt,
                speaker_id=initial_speaker.participant_id if initial_speaker else None
            )
            
            logger.info(f"Conversation {self.conversation_id} started with initial prompt")
            return initial_message
        
        logger.info(f"Conversation {self.conversation_id} started")
        return None
    
    def _initialize_turn_management(self):
        """Initialize turn-taking management system."""
        if self.turn_policy == TurnPolicy.ROUND_ROBIN:
            # Simple round-robin order
            active_participants = [p for p in self.participants.values() if p.is_active]
            self.speaking_queue.extend([p.participant_id for p in active_participants])
        
        elif self.turn_policy == TurnPolicy.SMART_CONTEXTUAL:
            # Initialize with engagement-based order
            self._update_speaking_queue_contextual()
        
        elif self.turn_policy == TurnPolicy.RANDOM:
            # Random selection (no queue needed)
            pass
        
        # Set initial speaker
        self.current_speaker = self._select_next_speaker()
        
        logger.debug(f"Turn management initialized with policy: {self.turn_policy.value}")
    
    def _select_initial_speaker(self) -> Optional[ConversationParticipant]:
        """Select the initial speaker for the conversation."""
        # Prefer facilitators or highest priority participants
        facilitators = [p for p in self.participants.values() if p.role == "facilitator"]
        if facilitators:
            return facilitators[0]
        
        # Otherwise, select participant with highest turn priority
        active_participants = [p for p in self.participants.values() if p.is_active]
        if active_participants:
            return max(active_participants, key=lambda p: p.turn_priority)
        
        return None
    
    async def process_turn(
        self, 
        input_message: str,
        speaker_id: Optional[str] = None,
        constraints: Optional[Dict[str, Any]] = None
    ) -> ConversationMessage:
        """
        Process a conversation turn.
        
        Args:
            input_message: Input message for the turn
            speaker_id: Optional specific speaker ID (overrides turn management)
            constraints: Optional generation constraints
            
        Returns:
            Generated conversation message
        """
        if self.state != ConversationState.ACTIVE:
            raise ValueError(f"Cannot process turns in {self.state.value} state")
        
        if self.current_turn >= self.max_turns:
            await self.complete_conversation("Maximum turns reached")
            raise ValueError("Conversation has reached maximum turns")
        
        start_time = time.time()
        
        try:
            # Determine speaker
            if speaker_id and speaker_id in self.participants:
                current_speaker_id = speaker_id
            else:
                current_speaker_id = self.current_speaker or self._select_next_speaker()
            
            if not current_speaker_id:
                raise ValueError("No active speaker available")
            
            # Update turn tracking
            self.current_turn += 1
            self.current_speaker = current_speaker_id
            self.turn_history.append((self.current_turn, current_speaker_id))
            
            # Update participant activity
            participant = self.participants[current_speaker_id]
            participant.last_activity = datetime.now()
            participant.message_count += 1
            
            # Create generation request
            request = GenerationRequest(
                speaker_id=current_speaker_id,
                context=self.context,
                input_message=input_message,
                conversation_history=self._get_conversation_history(),
                constraints=constraints or {},
                target_accuracy=0.95,
                max_response_length=500,
                temperature=0.7
            )
            
            # Generate response
            response = await self.dialogue_generator.generate_response(request)
            
            # Create conversation message
            message = ConversationMessage(
                message_id=str(uuid.uuid4()),
                conversation_id=self.conversation_id,
                participant_id=current_speaker_id,
                content=response.generated_text,
                timestamp=datetime.now(),
                turn_number=self.current_turn,
                accuracy_score=response.accuracy_score,
                cultural_authenticity=response.cultural_authenticity,
                confidence_score=response.confidence_score,
                engagement_score=self._calculate_engagement_score(response.generated_text),
                historical_appropriateness=response.cultural_authenticity,
                metadata=response.metadata
            )
            
            # Store message
            self.messages.append(message)
            self.message_index[message.message_id] = message
            
            # Update conversation context
            self._update_conversation_context(message)
            
            # Update analytics
            self._update_analytics(message, response)
            
            # Prepare next speaker
            self._prepare_next_speaker(message)
            
            # Update performance stats
            turn_time = (time.time() - start_time) * 1000
            self._update_performance_stats(turn_time, True)
            
            # Update last activity
            self.last_activity = datetime.now()
            
            logger.debug(f"Turn {self.current_turn} completed by {current_speaker_id}")
            
            return message
        
        except Exception as e:
            logger.error(f"Turn processing failed: {e}")
            self._update_performance_stats(0, False)
            raise
    
    def _select_next_speaker(self) -> Optional[str]:
        """Select the next speaker based on turn policy."""
        active_participants = [p for p in self.participants.values() if p.is_active]
        
        if not active_participants:
            return None
        
        if self.turn_policy == TurnPolicy.ROUND_ROBIN:
            if self.speaking_queue:
                return self.speaking_queue.popleft()
            else:
                # Refill queue
                self.speaking_queue.extend([p.participant_id for p in active_participants])
                return self.speaking_queue.popleft() if self.speaking_queue else None
        
        elif self.turn_policy == TurnPolicy.RANDOM:
            return np.random.choice([p.participant_id for p in active_participants])
        
        elif self.turn_policy == TurnPolicy.SMART_CONTEXTUAL:
            return self._select_contextual_speaker()
        
        elif self.turn_policy == TurnPolicy.FACILITATOR_CONTROLLED:
            # Manual control - return current speaker or None
            return self.next_speaker
        
        return None
    
    def _select_contextual_speaker(self) -> Optional[str]:
        """Select next speaker based on conversational context."""
        active_participants = [p for p in self.participants.values() if p.is_active]
        
        if not active_participants:
            return None
        
        # Calculate speaking scores based on various factors
        scores = {}
        
        for participant in active_participants:
            score = 0.0
            
            # Base priority
            score += participant.turn_priority * 0.3
            
            # Engagement level
            score += participant.engagement_level * 0.2
            
            # Time since last spoke (encourage balanced participation)
            turns_since_spoke = self._turns_since_participant_spoke(participant.participant_id)
            if turns_since_spoke > 0:
                score += min(turns_since_spoke * 0.1, 0.5)
            
            # Topic relevance (if participant has relevant expertise)
            if self.current_topic and participant.expertise_areas:
                topic_relevance = self._calculate_topic_relevance(
                    participant.expertise_areas, self.current_topic.name
                )
                score += topic_relevance * 0.2
            
            # Cross-temporal interaction bonus
            if self._would_create_cross_temporal_interaction(participant.participant_id):
                score += 0.15
            
            scores[participant.participant_id] = score
        
        # Select participant with highest score
        best_participant = max(scores.items(), key=lambda x: x[1])
        return best_participant[0]
    
    def _turns_since_participant_spoke(self, participant_id: str) -> int:
        """Count turns since participant last spoke."""
        for i, (turn_num, speaker_id) in enumerate(reversed(self.turn_history)):
            if speaker_id == participant_id:
                return i
        return len(self.turn_history)
    
    def _calculate_topic_relevance(self, expertise_areas: List[str], topic_name: str) -> float:
        """Calculate how relevant participant's expertise is to current topic."""
        if not expertise_areas or not topic_name:
            return 0.0
        
        # Simple keyword matching - could be enhanced with semantic similarity
        topic_words = set(topic_name.lower().split())
        expertise_words = set(' '.join(expertise_areas).lower().split())
        
        overlap = len(topic_words.intersection(expertise_words))
        return min(overlap * 0.2, 1.0)
    
    def _would_create_cross_temporal_interaction(self, participant_id: str) -> bool:
        """Check if selecting this participant would create cross-temporal interaction."""
        if not self.messages:
            return False
        
        last_speaker_id = self.messages[-1].participant_id
        if last_speaker_id == participant_id:
            return False
        
        last_speaker = self.participants.get(last_speaker_id)
        current_participant = self.participants.get(participant_id)
        
        if not last_speaker or not current_participant:
            return False
        
        # Different historical periods = cross-temporal interaction
        return last_speaker.historical_period != current_participant.historical_period
    
    def _update_speaking_queue_contextual(self):
        """Update speaking queue for contextual turn policy."""
        # This would implement dynamic queue updates based on context
        pass
    
    def _get_conversation_history(self, limit: int = 10) -> List[Dict[str, str]]:
        """Get recent conversation history for context."""
        recent_messages = list(self.messages)[-limit:]
        
        history = []
        for message in recent_messages:
            participant = self.participants.get(message.participant_id)
            role = "assistant" if participant else "user"
            
            history.append({
                "role": role,
                "content": message.content,
                "participant_id": message.participant_id,
                "participant_name": participant.name if participant else "Unknown",
                "historical_period": participant.historical_period if participant else "",
                "timestamp": message.timestamp.isoformat(),
                "turn_number": message.turn_number
            })
        
        return history
    
    def _update_conversation_context(self, message: ConversationMessage):
        """Update conversation context for coherence tracking."""
        context_entry = {
            'turn_number': message.turn_number,
            'participant_id': message.participant_id,
            'content': message.content,
            'timestamp': message.timestamp.isoformat(),
            'accuracy_score': message.accuracy_score,
            'cultural_authenticity': message.cultural_authenticity,
            'engagement_score': message.engagement_score
        }
        
        self.conversation_context.append(context_entry)
        
        # Update topic tracking
        self._update_topic_tracking(message)
    
    def _update_topic_tracking(self, message: ConversationMessage):
        """Update topic tracking based on message content."""
        # Simple topic detection based on keywords
        # In a real implementation, this could use NLP for topic modeling
        
        content_words = set(message.content.lower().split())
        
        # Check if current topic is still active
        if self.current_topic:
            topic_words = set(self.current_topic.name.lower().split())
            if len(content_words.intersection(topic_words)) > 0:
                # Topic continues
                self.current_topic.participants_involved.append(message.participant_id)
                self.current_topic.engagement_level = (
                    (self.current_topic.engagement_level + message.engagement_score) / 2.0
                )
                return
            else:
                # Topic ended
                self.current_topic.end_turn = message.turn_number - 1
                self.topic_tracking.append(self.current_topic)
                self.current_topic = None
        
        # Detect new topic (simplified)
        potential_topics = ['philosophy', 'science', 'politics', 'art', 'religion', 'war', 'peace']
        for topic in potential_topics:
            if topic in message.content.lower():
                self.current_topic = ConversationTopic(
                    topic_id=str(uuid.uuid4()),
                    name=topic,
                    description=f"Discussion about {topic}",
                    historical_context=self.context.historical_period,
                    participants_involved=[message.participant_id],
                    start_turn=message.turn_number,
                    engagement_level=message.engagement_score
                )
                break
    
    def _calculate_engagement_score(self, content: str) -> float:
        """Calculate engagement score for a message."""
        # Simple heuristics for engagement
        score = 0.5  # Base score
        
        # Length factor
        word_count = len(content.split())
        if word_count > 20:
            score += 0.1
        if word_count > 50:
            score += 0.1
        
        # Question presence (indicates engagement)
        if '?' in content:
            score += 0.15
        
        # Emotional expressions
        emotional_words = ['wonderful', 'fascinating', 'intriguing', 'remarkable', 'excellent']
        for word in emotional_words:
            if word in content.lower():
                score += 0.05
                break
        
        # Direct address to others
        if any(name in content for name in [p.name for p in self.participants.values()]):
            score += 0.1
        
        return min(score, 1.0)
    
    def _update_analytics(self, message: ConversationMessage, response):
        """Update conversation analytics."""
        self.analytics.total_turns += 1
        self.analytics.total_messages += 1
        
        # Update participant stats
        participant_id = message.participant_id
        if participant_id not in self.analytics.participants_stats:
            self.analytics.participants_stats[participant_id] = {
                'message_count': 0,
                'average_accuracy': 0.0,
                'average_cultural_authenticity': 0.0,
                'average_engagement': 0.0,
                'total_response_time': 0.0
            }
        
        stats = self.analytics.participants_stats[participant_id]
        stats['message_count'] += 1
        
        # Update running averages
        count = stats['message_count']
        stats['average_accuracy'] = (
            (stats['average_accuracy'] * (count - 1) + message.accuracy_score) / count
        )
        stats['average_cultural_authenticity'] = (
            (stats['average_cultural_authenticity'] * (count - 1) + 
             message.cultural_authenticity) / count
        )
        stats['average_engagement'] = (
            (stats['average_engagement'] * (count - 1) + message.engagement_score) / count
        )
        
        # Track trends over time
        self.analytics.engagement_over_time.append((message.turn_number, message.engagement_score))
        self.analytics.accuracy_over_time.append((message.turn_number, message.accuracy_score))
        self.analytics.cultural_authenticity_over_time.append(
            (message.turn_number, message.cultural_authenticity)
        )
        
        # Track anachronisms and corrections
        if response.anachronism_detected:
            self.analytics.anachronisms_detected += 1
        
        if response.metadata.get('corrections_applied', False):
            self.analytics.corrections_applied += 1
        
        # Track cross-temporal interactions
        if self._is_cross_temporal_interaction(message):
            self.analytics.cross_temporal_interactions += 1
    
    def _is_cross_temporal_interaction(self, message: ConversationMessage) -> bool:
        """Check if this message represents a cross-temporal interaction."""
        if len(self.messages) < 2:
            return False
        
        # Get previous message
        previous_messages = list(self.messages)
        if len(previous_messages) < 2:
            return False
        
        prev_message = previous_messages[-2]  # Second to last
        current_participant = self.participants.get(message.participant_id)
        prev_participant = self.participants.get(prev_message.participant_id)
        
        if not current_participant or not prev_participant:
            return False
        
        # Different historical periods = cross-temporal interaction
        return current_participant.historical_period != prev_participant.historical_period
    
    def _prepare_next_speaker(self, message: ConversationMessage):
        """Prepare the next speaker for the following turn."""
        if self.turn_policy == TurnPolicy.FACILITATOR_CONTROLLED:
            # Manual control - don't auto-select
            return
        
        self.next_speaker = self._select_next_speaker()
        
        # Update speaking queue if needed
        if self.turn_policy == TurnPolicy.ROUND_ROBIN and self.speaking_queue:
            # Add current speaker back to end of queue
            self.speaking_queue.append(message.participant_id)
    
    def _update_performance_stats(self, turn_time: float, success: bool):
        """Update performance statistics."""
        if success:
            self.performance_stats['successful_turns'] += 1
        else:
            self.performance_stats['failed_turns'] += 1
        
        total_turns = (
            self.performance_stats['successful_turns'] + 
            self.performance_stats['failed_turns']
        )
        
        if success and total_turns > 0:
            self.performance_stats['total_generation_time'] += turn_time
            self.performance_stats['average_turn_time'] = (
                self.performance_stats['total_generation_time'] / 
                self.performance_stats['successful_turns']
            )
    
    async def _add_system_message(
        self, 
        content: str, 
        speaker_id: Optional[str] = None
    ) -> ConversationMessage:
        """Add a system message to the conversation."""
        message = ConversationMessage(
            message_id=str(uuid.uuid4()),
            conversation_id=self.conversation_id,
            participant_id=speaker_id or "system",
            content=content,
            timestamp=datetime.now(),
            turn_number=0,  # System messages don't count as turns
            metadata={'type': 'system'}
        )
        
        self.messages.append(message)
        self.message_index[message.message_id] = message
        
        return message
    
    def set_next_speaker(self, participant_id: str):
        """Manually set the next speaker (for facilitator control)."""
        if participant_id in self.participants:
            self.next_speaker = participant_id
            logger.debug(f"Next speaker set to {participant_id}")
        else:
            logger.warning(f"Cannot set unknown participant {participant_id} as next speaker")
    
    def pause_conversation(self):
        """Pause the conversation."""
        if self.state == ConversationState.ACTIVE:
            self.state = ConversationState.PAUSED
            logger.info(f"Conversation {self.conversation_id} paused")
    
    def resume_conversation(self):
        """Resume a paused conversation."""
        if self.state == ConversationState.PAUSED:
            self.state = ConversationState.ACTIVE
            self.last_activity = datetime.now()
            logger.info(f"Conversation {self.conversation_id} resumed")
    
    async def complete_conversation(self, reason: str = "Manual completion"):
        """Complete the conversation."""
        self.state = ConversationState.COMPLETED
        self.completed_at = datetime.now()
        
        # Finalize topic tracking
        if self.current_topic:
            self.current_topic.end_turn = self.current_turn
            self.topic_tracking.append(self.current_topic)
        
        # Store conversation in memory system
        await self._persist_conversation()
        
        logger.info(f"Conversation {self.conversation_id} completed: {reason}")
    
    async def _persist_conversation(self):
        """Persist conversation to memory system."""
        try:
            conversation_data = {
                'conversation_id': self.conversation_id,
                'context': self.context.__dict__,
                'participants': {
                    p_id: {
                        'name': p.name,
                        'historical_period': p.historical_period,
                        'cultural_background': p.cultural_background,
                        'role': p.role,
                        'message_count': p.message_count
                    }
                    for p_id, p in self.participants.items()
                },
                'messages': [
                    {
                        'message_id': msg.message_id,
                        'participant_id': msg.participant_id,
                        'content': msg.content,
                        'timestamp': msg.timestamp.isoformat(),
                        'turn_number': msg.turn_number,
                        'accuracy_score': msg.accuracy_score,
                        'cultural_authenticity': msg.cultural_authenticity,
                        'confidence_score': msg.confidence_score
                    }
                    for msg in self.messages
                ],
                'analytics': {
                    'total_turns': self.analytics.total_turns,
                    'total_messages': self.analytics.total_messages,
                    'cross_temporal_interactions': self.analytics.cross_temporal_interactions,
                    'anachronisms_detected': self.analytics.anachronisms_detected,
                    'corrections_applied': self.analytics.corrections_applied
                },
                'completed_at': self.completed_at.isoformat() if self.completed_at else None
            }
            
            # Store in memory system
            await self.memory_manager.store_conversation(self.conversation_id, conversation_data)
            
        except Exception as e:
            logger.error(f"Failed to persist conversation {self.conversation_id}: {e}")
    
    def get_conversation_summary(self) -> Dict[str, Any]:
        """Get comprehensive conversation summary."""
        duration_minutes = 0.0
        if self.started_at:
            end_time = self.completed_at or datetime.now()
            duration_minutes = (end_time - self.started_at).total_seconds() / 60.0
        
        return {
            'conversation_id': self.conversation_id,
            'state': self.state.value,
            'context': {
                'historical_period': self.context.historical_period,
                'location': self.context.location,
                'topic': self.context.topic,
                'cultural_context': self.context.cultural_context
            },
            'participants': {
                p_id: {
                    'name': p.name,
                    'historical_period': p.historical_period,
                    'role': p.role,
                    'message_count': p.message_count,
                    'engagement_level': p.engagement_level,
                    'is_active': p.is_active
                }
                for p_id, p in self.participants.items()
            },
            'statistics': {
                'duration_minutes': duration_minutes,
                'total_turns': self.current_turn,
                'total_messages': len(self.messages),
                'cross_temporal_interactions': self.analytics.cross_temporal_interactions,
                'average_accuracy': (
                    sum(msg.accuracy_score for msg in self.messages) / len(self.messages)
                    if self.messages else 0.0
                ),
                'average_cultural_authenticity': (
                    sum(msg.cultural_authenticity for msg in self.messages) / len(self.messages)
                    if self.messages else 0.0
                ),
                'anachronisms_detected': self.analytics.anachronisms_detected,
                'corrections_applied': self.analytics.corrections_applied
            },
            'performance': {
                'successful_turns': self.performance_stats['successful_turns'],
                'failed_turns': self.performance_stats['failed_turns'],
                'average_turn_time_ms': self.performance_stats['average_turn_time'],
                'cross_temporal_exchanges': self.performance_stats['cross_temporal_exchanges']
            },
            'topics': [
                {
                    'name': topic.name,
                    'start_turn': topic.start_turn,
                    'end_turn': topic.end_turn,
                    'participants': len(set(topic.participants_involved)),
                    'engagement_level': topic.engagement_level
                }
                for topic in self.topic_tracking
            ],
            'created_at': self.created_at.isoformat(),
            'started_at': self.started_at.isoformat() if self.started_at else None,
            'completed_at': self.completed_at.isoformat() if self.completed_at else None
        }
    
    def export_conversation(self, format_type: str = "json") -> str:
        """Export conversation in specified format."""
        if format_type == "json":
            return json.dumps(self.get_conversation_summary(), indent=2, ensure_ascii=False)
        elif format_type == "text":
            return self._export_as_text()
        else:
            raise ValueError(f"Unsupported export format: {format_type}")
    
    def _export_as_text(self) -> str:
        """Export conversation as readable text."""
        lines = []
        lines.append(f"Cross-Temporal Conversation: {self.conversation_id}")
        lines.append(f"Historical Context: {self.context.historical_period}")
        lines.append(f"Location: {self.context.location}")
        lines.append(f"Topic: {self.context.topic}")
        lines.append("")
        
        lines.append("Participants:")
        for participant in self.participants.values():
            lines.append(f"  - {participant.name} ({participant.historical_period})")
        lines.append("")
        
        lines.append("Conversation:")
        for message in self.messages:
            if message.participant_id != "system":
                participant = self.participants.get(message.participant_id)
                if participant:
                    timestamp = message.timestamp.strftime("%H:%M")
                    lines.append(f"[Turn {message.turn_number}, {timestamp}] {participant.name}: {message.content}")
        
        return "\n".join(lines)
    
    def get_performance_metrics(self) -> Dict[str, Any]:
        """Get conversation performance metrics."""
        return {
            **self.performance_stats,
            'participants_count': len(self.participants),
            'active_participants': len([p for p in self.participants.values() if p.is_active]),
            'conversation_state': self.state.value,
            'turn_policy': self.turn_policy.value,
            'analytics': {
                'engagement_trend': self.analytics.engagement_over_time[-10:],  # Last 10 points
                'accuracy_trend': self.analytics.accuracy_over_time[-10:],
                'cultural_authenticity_trend': self.analytics.cultural_authenticity_over_time[-10:]
            }
        }